package com.jumi.microservice.warehousein.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.jumi.microservice.common.base.dto.ResponseResult;
import com.jumi.microservice.common.exception.ExceptionEnum;
import com.jumi.microservice.common.exception.ExceptionSupply;
import com.jumi.microservice.common.wdt.WdtUtils;
import com.jumi.microservice.material.dto.warehouse.JmWarehouseResponse;
import com.jumi.microservice.material.mapper.JmMaterialMapper;
import com.jumi.microservice.material.service.JmWarehouseService;
import com.jumi.microservice.stock.domain.StockDTO;
import com.jumi.microservice.stock.domain.StockDetailDTO;
import com.jumi.microservice.stock.service.StockService;
import com.jumi.microservice.warehousein.domain.JmWarehouseIn;
import com.jumi.microservice.warehousein.domain.JmWarehouseInAuditLog;
import com.jumi.microservice.warehousein.domain.JmWarehouseInDetail;
import com.jumi.microservice.warehousein.domain.JmWarehouseInStock;
import com.jumi.microservice.warehousein.dto.JmWarehouseInAuditRequest;
import com.jumi.microservice.warehousein.dto.JmWarehouseInDetailRequest;
import com.jumi.microservice.warehousein.dto.JmWarehouseInRequest;
import com.jumi.microservice.warehousein.dto.JmWarehouseInResponse;
import com.jumi.microservice.warehousein.mapper.JmWarehouseInAuditLogMapper;
import com.jumi.microservice.warehousein.mapper.JmWarehouseInDetailMapper;
import com.jumi.microservice.warehousein.mapper.JmWarehouseInMapper;
import com.jumi.microservice.warehousein.mapper.JmWarehouseInStockMapper;
import com.jumi.microservice.warehousein.service.JmWarehouseInService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author ssk
 * @create 2020/8/11 15:26
 **/
@Service
public class JmWarehouseInServiceImpl implements JmWarehouseInService {

    @Resource
    private JmWarehouseInMapper inMapper;

    @Resource
    private JmWarehouseInDetailMapper detailMapper;

    @Resource
    private JmMaterialMapper materialMapper;

    @Resource
    private JmWarehouseInStockMapper stockMapper;

    @Resource
    private JmWarehouseInAuditLogMapper auditLogMapper;


    @Resource
    private JmWarehouseService warehouseService;


    @Resource
    private StockService stockService;

    @Override
    @Transactional
    public int save(JmWarehouseIn warehouseIn) {
        int rows = inMapper.save(warehouseIn);
        List objs = warehouseIn.getDetails();
        List<JmWarehouseInDetail> details = new ArrayList<>();
        int totalNum = 0;
        for (Object obj : objs) {
            JmWarehouseInDetail detail = new JmWarehouseInDetail();
            try {
                ((JmWarehouseInDetailRequest) obj).clone(detail);
            } catch (Exception e) {
                throw ExceptionEnum.FAIL_CHANGE.newException();
            }
            totalNum += detail.getInNum();
            detail.setCreateBy(warehouseIn.getCreateBy());
            detail.setInId(warehouseIn.getInId());
            details.add(detail);
        }
        if (warehouseIn.getTotalNum() != totalNum) {
            throw new ExceptionSupply(500, "库存总量与物料库存之和不匹配!").newException();
        }
        detailMapper.saveBatch(details);
        return rows;
    }

    @Override
    @Transactional
    public int update(JmWarehouseIn warehouseIn) {
        warehouseIn.setStatus(0);
        int rows = inMapper.update(warehouseIn);
        List objs = warehouseIn.getDetails();
        List<JmWarehouseInDetail> details = new ArrayList<>();
        int totalNum = 0;
        for (Object obj : objs) {
            JmWarehouseInDetail detail = new JmWarehouseInDetail();
            try {
                ((JmWarehouseInDetailRequest) obj).clone(detail);
            } catch (Exception e) {
                throw ExceptionEnum.FAIL_CHANGE.newException();
            }
            totalNum += detail.getInNum();
            detail.setUpdateBy(warehouseIn.getUpdateBy());
            details.add(detail);
        }

        if (warehouseIn.getTotalNum() != totalNum) {
            throw new ExceptionSupply(500, "库存总量与物料库存之和不匹配!").newException();
        }
        detailMapper.updateBatch(details);
        return rows;
    }

    @Override
    public JmWarehouseInResponse findById(Long inId) {
        JmWarehouseInResponse inResponse = inMapper.findById(inId);
        Long warehouseId = inResponse.getWarehouseId();
        JmWarehouseResponse warehouseResponse = warehouseService.findById(warehouseId);
        StringBuffer addrSb = new StringBuffer();
        String addr = addrSb.append(warehouseResponse.getProvinceName()).append(" ").append(warehouseResponse.getCityName())
                .append(" ").append(warehouseResponse.getAreaName()).append(" ").append(warehouseResponse.getAddress()).toString();
        inResponse.setWarehouseAddr(addr);
        return inResponse;
    }

    @Override
    public List<JmWarehouseInResponse> findAll(JmWarehouseInRequest warehouseIn) {
        return inMapper.findAll(warehouseIn);
    }

    @Override
    @Transactional
    public int auditBatch(Long[] inIds, String auditRemark, BigDecimal price, Integer status, String auditBy) {
        int rows = 0;
        Map<String, Object> params = new HashMap<>();
        if (status == 1) {
            //成本价
            params.put("inIds", inIds);
            params.put("price", price);
            detailMapper.auditBatch(params);
            params.clear();
            Long[] materialIds = detailMapper.findMaterialIdsByInIds(inIds);
            params.put("materialIds", materialIds);
            params.put("price", price);
            //同步更新物料成本价
            materialMapper.syncPrice(params);
            params.clear();
            if (StringUtils.isBlank(auditRemark)) {
                auditRemark = "审核通过";
            }

            // 审核条目
            List<JmWarehouseInStock> auditIns = stockMapper.findByInIds(inIds);
            // 入库条目
            List<JmWarehouseInStock> realIns = new ArrayList<>();
            // 推送旺店通入库申请
            List<JmWarehouseInStock> wdtIns = new ArrayList<>();

            Set inIdSet = new HashSet();
            Set wdtIdSet = new HashSet();
            for (JmWarehouseInStock inObj : auditIns) {
                if (inObj.getIsNormal() == 1) {
                    realIns.add(inObj);
                    inIdSet.add(inObj.getInId());
                } else {
                    wdtIns.add(inObj);
                    wdtIdSet.add(inObj.getInId());
                }
            }
            if (realIns.size() > 0) {
                //更改入库状态
                params.put("inIds", inIdSet);
                params.put("auditRemark", auditRemark);
                params.put("status", 2);
                params.put("updateBy", auditBy);
                rows += inMapper.auditBatch(params);
                params.clear();
                //入库记录
                stockMapper.saveBatch(auditIns);

                boolean isFailed = false;
                for (JmWarehouseInStock inStock : realIns) {
                    ResponseResult rsData = save2Stock(inStock);
                    if (rsData == null || 200 != rsData.getCode()) {
                        isFailed = true;
                        break;
                    }
                }
                if (isFailed) {
                    throw new ExceptionSupply(500, "库存加入失败!").newException();
                }
            }

            if (wdtIns.size() > 0) {
                List<Map<String, Object>> details = detailMapper.findDetailByInIds(inIds);
                JSONObject json = WdtUtils.purchasePush(details);
                if (json.getInteger("code") == 0) {
                    String purchaseCode = json.getString("message");
                    params.put("inIds", wdtIdSet);
                    params.put("purchaseCode", purchaseCode);
                    inMapper.updatePurchaseCode(params);
                } else {
                    throw new ExceptionSupply(500, "推送到旺店通失败!").newException();
                }
                //更改入库状态
                params.put("inIds", wdtIdSet);
                params.put("auditRemark", auditRemark);
                params.put("status", 1);
                params.put("updateBy", auditBy);
                rows += inMapper.auditBatch(params);
                params.clear();

            }
        } else {
            params.put("inIds", inIds);
            params.put("auditRemark", auditRemark);
            params.put("status", status);
            params.put("updateBy", auditBy);
            rows += inMapper.auditBatch(params);
            params.clear();
        }

        //审核日志插入
        List<JmWarehouseInAuditLog> auditLogs = auditLogMapper.findAuditLogsByInIds(inIds);
        auditLogMapper.saveBatch(auditLogs);
        return rows;
    }

    @Override
    public List<JmWarehouseInAuditLog> findAuditLogById(Long inId) {
        return auditLogMapper.findAuditLogsByInId(inId);
    }

    @Override
    @Transactional
    public int audit(JmWarehouseInAuditRequest auditRequest) {
        Map<String, Object> params = new HashMap<>();
        Long[] inIds = {auditRequest.getInId()};
        List<JmWarehouseInDetailRequest> detailRequests = auditRequest.getDetails();
        int rows = 0;
        if (auditRequest.getStatus() == 1) {
            //成本价
            List<Map<String, Object>> paramList = new ArrayList<>();
            for (JmWarehouseInDetailRequest detailRequest : detailRequests) {
                Map<String, Object> param = new HashMap<>();
                param.put("materialId", detailRequest.getMaterialId());
                param.put("price", detailRequest.getPrice());
                param.put("detailId", detailRequest.getDetailId());
                paramList.add(param);
            }
            detailMapper.audit(paramList);

            //同步更新物料成本价
            materialMapper.syncPriceBatch(paramList);

            if (StringUtils.isBlank(auditRequest.getAuditRemark())) {
                auditRequest.setAuditRemark("审核通过");
            }

            // 审核条目
            List<JmWarehouseInStock> auditIns = stockMapper.findByInIds(inIds);
            int isNormal = 0;
            JmWarehouseInStock inStock = new JmWarehouseInStock();
            try {
                inStock = auditIns.get(0);
                isNormal = inStock.getIsNormal();
            } catch (Exception e) {
                throw new ExceptionSupply(500, "数据异常!").newException();
            }

            if (isNormal == 1) {
                //更改入库状态
                params.put("inIds", inIds);
                params.put("auditRemark", auditRequest.getAuditRemark());
                params.put("status", 2);
                params.put("updateBy", auditRequest.getAuditBy());
                rows = inMapper.auditBatch(params);
                params.clear();
                //入库记录
                int stockRows = stockMapper.saveBatch(auditIns);

                ResponseResult rsData = save2Stock(inStock);
                if (rsData == null || 200 != rsData.getCode()) {
                    throw new ExceptionSupply(500, "库存加入失败!").newException();
                }

            } else {
                List<Map<String, Object>> details = detailMapper.findDetailByInIds(inIds);
                JSONObject json = WdtUtils.purchasePush(details);
                if (json.getInteger("code") == 0) {
                    String purchaseCode = json.getString("message");
                    params.put("inIds", inIds);
                    params.put("purchaseCode", purchaseCode);
                    inMapper.updatePurchaseCode(params);
                } else {
                    throw new ExceptionSupply(500, "推送到旺店通失败!").newException();
                }
                params.put("inIds", inIds);
                params.put("auditRemark", auditRequest.getAuditRemark());
                params.put("status", auditRequest.getStatus());
                params.put("updateBy", auditRequest.getAuditBy());
                rows = inMapper.auditBatch(params);
                params.clear();
            }


        }else if(auditRequest.getStatus() == 3){
            params.put("inIds", inIds);
            params.put("auditRemark", auditRequest.getAuditRemark());
            params.put("status", auditRequest.getStatus());
            params.put("updateBy", auditRequest.getAuditBy());
            rows = inMapper.auditBatch(params);
            params.clear();
        }

        //审核日志插入
        List<JmWarehouseInAuditLog> auditLogs = auditLogMapper.findAuditLogsByInIds(inIds);
        auditLogMapper.saveBatch(auditLogs);
        return rows;
    }

    @Override
    @Transactional
    public int syncPurchaseOrders(String auditBy) {
        String[] purchaseCodes = inMapper.findAllPurchaseCodes();
        if (purchaseCodes != null && purchaseCodes.length > 0) {
            Long[] inIds = inMapper.findByPurchaseCodes(purchaseCodes);
            if (inIds == null || inIds.length == 0)
                return 0;
            Map<String, Object> params = new HashMap<>();
            params.put("inIds", inIds);
            params.put("status", 2);
            params.put("updateBy", auditBy);
            int rows = inMapper.auditBatch(params);
            List<JmWarehouseInStock> auditIns = stockMapper.findByInIds(inIds);
            //入库记录
            stockMapper.saveBatch(auditIns);
            for (JmWarehouseInStock inStock : auditIns) {
                ResponseResult rsData = save2Stock(inStock);
                if (rsData == null || 200 != rsData.getCode()) {
                    throw new ExceptionSupply(500, "库存加入失败!").newException();
                }
            }
            //审核日志插入
            List<JmWarehouseInAuditLog> auditLogs = auditLogMapper.findAuditLogsByInIds(inIds);
            auditLogMapper.saveBatch(auditLogs);
            return rows;
        } else {
            return 0;
        }
    }

    /**
     * 入库
     *
     * @param inStock
     */
    private ResponseResult save2Stock(JmWarehouseInStock inStock) {
        StockDTO stockDTO = new StockDTO();
        stockDTO.setGoodsId(inStock.getGoodsId());
        stockDTO.setGoodsCode(inStock.getGoodsCode());
        stockDTO.setWarehouseId(inStock.getWarehouseId());
        stockDTO.setBatchCode(inStock.getBatchCode());
        stockDTO.setChangeType(inStock.getInTypeId().intValue());
        int totalNum = 0;
        List<StockDetailDTO> detailDTOS = new ArrayList<>();
        List<JmWarehouseInDetailRequest> details = detailMapper.findDetailByInId(inStock.getInId());
        for (JmWarehouseInDetailRequest detailRequest : details) {
            if(detailRequest.getInNum() > 0){
                StockDetailDTO detailDTO = new StockDetailDTO();
                detailDTO.setMaterialId(detailRequest.getMaterialId());
                detailDTO.setMaterialCode(detailRequest.getMaterialCode());
                if (inStock.getWarehouseType() == 0) {
                    detailDTO.setInStockNum(detailRequest.getInNum());
                    detailDTO.setInStockDamageNum(0);
                } else {
                    detailDTO.setInStockNum(0);
                    detailDTO.setInStockDamageNum(detailRequest.getInNum());
                }
                detailDTOS.add(detailDTO);
                totalNum += detailRequest.getInNum();
            }
        }
        stockDTO.setUpdateBy(inStock.getCreateBy());
        if (inStock.getWarehouseType() == 0) {
            stockDTO.setInStockTotalNum(totalNum);
            stockDTO.setInStockDamageTotalNum(0);
        } else {
            stockDTO.setInStockTotalNum(0);
            stockDTO.setInStockDamageTotalNum(totalNum);
        }
        stockDTO.setStockDetailDtoList(detailDTOS);
        stockDTO.setChangeReasonId(inStock.getInId());
        stockDTO.setIsGeneralWarehouse((byte)1);
        return stockService.inStock(stockDTO);
    }
}
